<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Flow;
use App\Models\Rebate;
use App\Models\User;
use App\Models\Withdraw;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;

class UserController extends Controller
{

    //todo  获取用户
    public function select_delivery_done(Request $request) {
        $request->validate([
            'token'                 =>  ['required','string'],
            'selected_delivery_id'  =>  [Rule::exists('deliveries','id')]
        ]);

        User::where()->update(['delivery_id'=>$request->post('selected_delivery_id')]);

        return $this->response(0,[],"设置成功");
    }

    /**
     * 绑定用户上下级关系
     * @param Request $request
     */
    public function bind_parent(Request $request){
        $request->validate([
           'uid'    =>  'required|integer',
           'pid'    =>  'required|integer|different:uid ',
        ]);
        $user = User::findOrFail($request->post('uid'));
        $parent_user = User::findOrFail($request->post('pid'));

        //未绑定上级用户时
        if ($user->pid == 0) {
            //当前用户不能和上级用户互为上下级
            if ($user->id != $parent_user->pid) {
                $user->pid = $request->post('pid');
                $user->save();
                $this->response(0,[],'绑定成功');
            }else {
                $this->response(0,[],'绑定失败',['当前用户不能是上级用户的上级用户']);
            }
        }else {
            $this->response(1,[],'绑定失败',['用户已经有上级']);
        }
    }

    //我的一级好友
    function first_friends(Request $request) {
        $request->validate([
           'api_token'  =>  'required|string'
        ]);
        $user_id = User::where('api_token',$request->get('api_token'))->value('id');
        $user_model = new User();
        if ($user_id) {
            $where = ['pid'=>$user_id];
            $first_friends = $user_model->get_users($where,$request->get('limit'))->toArray();
            return $this->response(0,$first_friends);
        }else {
            $where = ['pid'=> -1];
            $first_friends = $user_model->get_users($where,$request->get('limit'))->toArray();
            return $this->response(0,$first_friends);
        }
    }

    //我的二级好友
    function second_friends(Request $request) {
        $request->validate([
           'api_token'  =>  'required|string'
        ]);
        $user_id = User::where('api_token',$request->get('api_token'))->value('id');
        $model = new User();
        if ($user_id) {
            //获取一级好友的id集合
            $first_friends = $model->get_users(['pid'=>$user_id])->pluck('id')->toArray();
            if ($first_friends) {
                $first_friends = implode(",",$first_friends);
                $where[] = [DB::raw("pid in ({$first_friends})"),1];
                return $this->response(0,$model->get_users($where,$request->get('limit'),true)->toArray());
            }else {
                return $this->response(0,$model->get_users(['pid' => -1],$request->get('limit'),true)->toArray());
                //return $this->response(0,[],'没有二级好友',['second_friends'=>'没有二级好友']);
            }
        }else {
            return $this->response(0,$model->get_users(['pid' => -1],$request->get('limit'),true)->toArray());
            //return $this->response(1,[],'用户不存在',['user'=>'用户不存在']);
        }
    }

    //我的小程序码
    function my_mpcode(Request $request) {
        $user = User::where('api_token',$request->get('api_token'))->select('mp_code','id')->first();
        if ($user->mp_code) {
            return $user->mp_code;
        }

        $mini_program = new MiniProgramController();
        $user->mp_code = $mini_program->getUnlimited('pid',$user->id,'pages/my/index');
        $user->save();
        return $this->response(0,['mp_code'=>$user->mp_code]);
    }

    //用户信息
    function user_info(Request $request) {
        $info = User::where('api_token',$request->get('api_token'))
            ->select('total_money','current_money','nickname','avatar','pid','mobile','username','openid','address','mp_code','can_hexiao','address_title')
            ->first()->toArray();
        return $this->response(0,$info);
    }


    //用户金币记录
    function money(Request $request) {
        $whereIN = [WITHDRAW,REBATE];
        $request->validate([
            'type'  =>  ["sometimes",Rule::in($whereIN)]
        ]);
        $user = User::where('api_token',$request->get('api_token'))->first();
        if($type = $request->get('type')) {
            $whereIN = [$type];
        }

        $flows = Flow::where('user_id',$user->id)->whereIn('type',$whereIN)
                        ->paginate($request->get('limit',LIMIT))->toArray();

        foreach ($flows['data'] as &$item) {
            if ($item['type'] == REBATE) {//分润
                $item['rebate'] = Rebate::where('rebates.id',$item['business_id'])
                                        ->join('orders','orders.id','=','rebates.order_id')
                                        ->join('product_skus','product_skus.id','=','orders.sku_id')
                                        ->select('orders.mobile','orders.created_at','product_skus.title','orders.cash_money','rebates.level')->first();
            }elseif ($item['type'] == WITHDRAW) {//提现
                $item['withdraw'] = ['mobile'=>$user->mobile];
            }
        }

        return $this->response(0,$flows);
    }

    //用户提现  todo    频率限制、金额限制等要求
    function withdraw(Request $request) {
        $request->validate([
            'money'     =>  'required|numeric|gt:0',
            'username'  =>  'required'
        ]);
        //提现金额
        $money = $request->post('money');
        //收款人姓名
        $username = $request->post('username');

        DB::beginTransaction();
        $user = User::where('api_token',$request->get('api_token'))->lockForUpdate()->first();
        $user->username = $username;

        if (bccomp($money,$user->current_money,2) == 1) {
            DB::rollBack();
            return $this->response(1,[],'余额不足');
        }

        //生成提现单号
        $partner_trade_no = date('YmdHis') . $user->id . rand(1,1000);
        //插入提现记录
        $insert_withdraw_data = [
            'partner_trade_no'  =>  $partner_trade_no,
            'money'             =>  floor($money * 100),
            'user_id'           =>  $user->id
        ];
        $withdraw = Withdraw::create($insert_withdraw_data);

        //插入流水记录
        $insert_flow_data = [
            'money'         =>  $money,
            'type'          =>  WITHDRAW,
            'user_id'       =>  $user->id,
            'business_id'   =>  $withdraw->id
        ];
        Flow::create($insert_flow_data);

        //调用企业向微信用户个人付款接口
        $mp_controller = new MiniProgramController();
        $withdraw_result = $mp_controller->withdraw($partner_trade_no,$user->openid,$username,floor($money * 100));
        if ($withdraw_result['status'] == true) {//提现成功
            //修提现记录状态
            $withdraw->status = SUCCESS_WITHDRAW;
            $withdraw->payment_no = $withdraw_result['payment_no'];
            $withdraw->payment_time = $withdraw_result['payment_time'];
            $withdraw->save();
            //扣减用户余额
            $user->decrement('current_money',$money);
            $user->save();
            DB::commit();
            return $this->response(0,[],'提现成功');
        }else {//针对不同的错误码做不同的处理
            switch ($withdraw_result['err_code']) {
                case 'COMMUNICATE_FAIL':    //通讯失败
                case 'NO_AUTH':     //没有接口权限
                case 'AMOUNT_LIMIT':    //金额超限
                case 'PARAM_ERROR': //参数错误
                case 'OPENID_ERROR':    //openid错误
                case 'NOTENOUGH':// 商户余额不足
                case 'NAME_MISMATCH':   //姓名校验出错,如果要继续付款必须使用原商户订单号重试。
                case 'SIGN_ERROR':  //签名错误,检查请求参数和签名密钥KEY是否正确，如果要继续付款必须使用原商户订单号重试。
                case 'XML_ERROR':   //POST内容出错
                case 'FATAL_ERROR': //两次请求参数不一致
                case 'FREQ_LIMIT':  //调用接口过于频繁，请稍后再试，如果要继续付款必须使用原商户订单号重试。
                case 'MONEY_LIMIT': //付款额度已经超限，请参考接口使用条件，如果要继续付款必须使用原商户订单号重试。
                case 'CA_ERROR':    //商户API证书校验出错,如果要继续付款必须使用原商户订单号重试。
                case 'V2_ACCOUNT_SIMPLE_BAN':   //不支持给未实名用户付款，如果要继续付款必须使用原商户订单号重试。
                case 'PARAM_IS_NOT_UTF8':   //微信接口使用编码是UTF-8，请确认，如果要继续付款必须使用原商户订单号重试。
                case 'SENDNUM_LIMIT':   //向用户付款的次数超限了，请参考接口使用条件，如果要继续付款必须使用原商户订单号重试。
                case 'RECV_ACCOUNT_NOT_ALLOWED ':   //收款账户不在收款账户列表,请登陆商户平台，查看产品中心企业付款到零钱的产品配置
                case 'PAY_CHANNEL_NOT_ALLOWED': //本商户号未配置API发起能力,请登陆商户平台，查看产品中心企业付款到零钱的产品配置
                    DB::commit();
                    return $this->response(1,[],'提现失败');
                    break;
                case 'SEND_FAILED': //付款错误,请查单确认付款结果,以查单结果为准。
                case 'SYSTEMERROR': //系统繁忙，请稍后再试。微信内部接口调用发生错误。请先调用查询接口，查看此次付款结果，如结果为不明确状态（如订单号                                                                      //不存在），请务必使用原商户订单号进行重试。
                    //查询企业付款结果
                    $transfer_result = $mp_controller->get_transfer_info($partner_trade_no);
                    if ($transfer_result['status'] == true) {//付款成功
                        //修提现记录状态
                        $withdraw->status = SUCCESS_WITHDRAW;
                        $withdraw->payment_no = $transfer_result['detail_id'];
                        $withdraw->payment_time = $transfer_result['payment_time'];
                        $withdraw->save();
                        //扣减用户余额
                        $user->decrement('current_money',$money);
                        $user->save();
                        DB::commit();
                        return $this->response(0,[],'提现成功');
                    }else {
                        if (in_array($transfer_result['err_code'],['PROCESSING','SYSTEMERROR'])) {//处理中或者系统繁忙时
                            sleep(3);
                            //再次查询企业付款结果
                            $transfer_result = $mp_controller->get_transfer_info($partner_trade_no);
                            if ($transfer_result['status'] == true) {
                                //修提现记录状态
                                $withdraw->status = SUCCESS_WITHDRAW;
                                $withdraw->payment_no = $transfer_result['detail_id'];
                                $withdraw->payment_time = $transfer_result['payment_time'];
                                $withdraw->save();
                                //扣减用户余额
                                $user->decrement('current_money',$money);
                                $user->save();
                                DB::commit();
                                return $this->response(0,[],'提现成功');
                                break;
                            }elseif($transfer_result['status'] == false && $transfer_result['err_code'] == 'PROCESSING') {
                                //处理中。先把用户的余额扣除。防止企业支付成功，未扣除用户余额的情况出现
                                //修提现记录状态
                                $withdraw->status = PROCESSING_WITHDRAW;
                                $withdraw->save();
                                //扣减用户余额
                                $user->decrement('current_money',$money);
                                $user->save();
                                DB::commit();
                                return $this->response(0,[],'提现失败，请联系工作人员核实！');
                            }else {
                                DB::commit();
                                return $this->response(0,[],'提现失败');
                                break;
                            }
                        }else { //其他情况直提现失败
                            DB::commit();
                            return $this->response(0,[],'提现失败');
                        }
                    }
                    break;
                default:
                    DB::commit();
                    return $this->response(1,[],'提现失败');
            }
        }
    }
}
